package com.groupbuying.customer.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.parser.Feature;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipayEncrypt;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipaySystemOauthTokenRequest;
import com.alipay.api.request.AlipayUserInfoShareRequest;
import com.alipay.api.response.AlipaySystemOauthTokenResponse;
import com.alipay.api.response.AlipayUserInfoShareResponse;
import com.groupbuying.customer.constants.CustomerAlipayConstants;
import com.groupbuying.customer.utils.apiresult.ApiResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

public class AliUntil {
    private static final Logger logger = LoggerFactory.getLogger(AliUntil.class);

    /**
     * 获取用户信息
     *
     * @param accessToken
     * @return
     */

    public static AlipayUserInfoShareResponse getUserInfo(String accessToken, Map<String, String> param) throws Exception {

        AlipayClient alipayClient = new DefaultAlipayClient(param.get("url"), param.get("appId"),
                param.get("appPrivateKey"), param.get("format"), param.get("charset"),
                param.get("alipayPublicKey"), param.get("signType"));

        AlipayUserInfoShareRequest request = new AlipayUserInfoShareRequest();
        AlipayUserInfoShareResponse response = alipayClient.execute(request, accessToken);
        if (response.isSuccess()) {
            logger.info("用户信息获取成功");
            return response;
        }
        return null;
    }

    /**
     * 认证授权服务端获取access_token、user_id
     */
    public static AlipaySystemOauthTokenResponse getAccessToken(String authcode, Map<String, String> param) throws Exception {
        AlipayClient alipayClient = new DefaultAlipayClient(param.get("url"), param.get("appId"),
                param.get("appPrivateKey"), param.get("format"), param.get("charset"),
                param.get("alipayPublicKey"), param.get("signType"));

        logger.info("认证授权服务端获取 url:{},appId:{},appPrivateKey:{},format:{},charset:{},alipayPublicKey:{},signType:{}",
                param.get("url"), param.get("appId"), param.get("appPrivateKey"), param.get("format"), param.get("charset"),
                param.get("alipayPublicKey"), param.get("signType"));

        AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
        request.setGrantType(CustomerAlipayConstants.AUTHORIZATION_CODE);
        request.setCode(authcode);
        AlipaySystemOauthTokenResponse response = alipayClient.execute(request);
        return response;
    }

    /**
     * 刷新授权服务端获取access_token、user_id
     */
    public static AlipaySystemOauthTokenResponse getRefressToken(String refreshToken) throws Exception {
        AlipayClient alipayClient = new DefaultAlipayClient(CustomerAlipayConstants.URL, CustomerAlipayConstants.APP_ID,
                CustomerAlipayConstants.APP_PRIVATE_KEY, CustomerAlipayConstants.FORMAT, CustomerAlipayConstants.CHARSET,
                CustomerAlipayConstants.ALIPAY_PUBLIC_KEY, CustomerAlipayConstants.SIGN_TYPE);

        AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
        request.setGrantType(CustomerAlipayConstants.REFRESH_TOKEN);
        request.setCode(refreshToken);
        AlipaySystemOauthTokenResponse response = alipayClient.execute(request);
        return response;
    }

    /**
     * 支付宝用户授权手机号解密信息接口
     *
     * @param encryptedData
     * @param param
     * @return java.util.Map<java.lang.String, java.lang.String>
     * @Author Vincentxin
     * @Date 2019/9/27 11:53
     **/
    public static Map<String, String> authorizedMobileDecryption(String encryptedData, Map<String, String> param) {
        logger.info("需要解密的信息：{},支付宝SDK基础配置信息：{}", encryptedData, param);
        //1. 获取验签和解密所需要的参数
        Map<String, String> openapiResult = JSON.parseObject(encryptedData,
                new TypeReference<Map<String, String>>() {
                }, Feature.OrderedField);
        logger.info("支付宝验签和解密所需要的参数openapiResult：{}", openapiResult);
        String signType = CustomerAlipayConstants.SIGN_TYPE;
        String charset = CustomerAlipayConstants.CHARSET;
        String encryptType = CustomerAlipayConstants.ENCRYPT_TYPE;

        String sign = openapiResult.get("sign");
        String content = openapiResult.get("response");
        logger.info("content支付宝content：{}", content);
        logger.info("支付宝sign:{}", sign);
        //如果密文的
        boolean isDataEncrypted = !content.startsWith("{");
        logger.info("校验参数值:{}", isDataEncrypted);
        boolean signCheckPass = false;

        //2. 验签
        String signContent = content;
        String signVeriKey = param.get("alipayPublicKey");
        String decryptKey = CustomerAlipayConstants.ALIPAY_DECRYPTKEY_KEY_APP;
        if (isDataEncrypted) {
            signContent = "\"" + signContent + "\"";
            logger.info("查看是否是密文:{}", signContent);
        }
        try {
            signCheckPass = AlipaySignature.rsaCheck(signContent, sign, signVeriKey, charset, signType);
            logger.info("支付宝验签signCheckPass：{}", signCheckPass);
        } catch (AlipayApiException e) {
            logger.error("支付宝解密用户手机号验证签名异常：{}", e.getMessage());
            e.printStackTrace();
        }
        if (!signCheckPass) {
            logger.error("支付宝解密用户手机号验证签名失败");
            //TODO 这个地方需要重新构建一个map
            return null;
        }

        //3. 解密
        String message = null;
        Map<String, String> result = new HashMap<>();
        if (isDataEncrypted) {
            try {
                message = AlipayEncrypt.decryptContent(signContent, encryptType, decryptKey, charset);
                logger.info("支付宝解密message：{}", message);
            } catch (AlipayApiException e) {
                //解密异常
                logger.error("支付宝用户手机号解密异常");
                return null;
            }
        }
        result = JSON.parseObject(message, Map.class);
        logger.info("最后返回信息解密信息：{}", message);
        if ("10000".equals(result.get("code"))) {
            return result;
        } else {
            logger.error("解密信息错误，错误信息：{}", result);
            return null;
        }


    }
}
